# -*- coding: utf-8 -*-
# @File     : api.py
# @Author   : bingjia
# @Time     : 2020/8/6 17:23
# @Desc     : 检测api视图

import os
import ctypes
import inspect
import threading
from django.apps import apps
from django.conf import settings
from django.shortcuts import get_object_or_404, get_list_or_404

from operation.base.api import viewsets
from operation.base.api import response
from operation.base.api.utils.decorators import list_route, detail_route
from operation.trains.network.yolov5.detect_main import detect_main


from . import models
from . import validators
from . import permissions
from . import serializers

train_thread_pid = "0"


class CheckViewSet(viewsets.ModelViewSet):
    """
    检测视图
    """
    queryset = models.Defect.objects.all()
    "验证"
    validator_class = validators.DefectValidator
    "序列化"
    serializer_class = serializers.DefectSerializer
    "权限"
    permission_classes = (permissions.DefectPermission,)

    def _async_raise(tid, exctype):
        tid = ctypes.c_long(tid)
        if not inspect.isclass(exctype):
            exctype = type(exctype)
        res = ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, ctypes.py_object(exctype))
        if res == 0:
            raise ValueError("invalid thread id")
        elif res != 1:
            ctypes.pythonapi.PyThreadState_SetAsyncExc(tid, None)
            raise SystemError("PyThreadState_SetAsyncExc failed")

    @list_route(methods=["POST"])
    def start_check(self, request, *args, **kwargs):
        """
        启动检测
        """
        check_type = request.data.get('check_type', None)
        resource_id = kwargs.get("resource_id", None)
        project_object = get_object_or_404(apps.get_model("projects", "Project").objects.all(), pk=resource_id)

        self.check_permissions(request, "start_check", project_object)

        if check_type == "visible":
            # image_path = SrcData.objects.get(project=project_object).visible_image
            input_path = os.path.join(settings.ROOT_PATH, settings.STATIC_URL[1:-1], settings.PROJECT_PATH,
                                      resource_id, "data", "src", "visible")
            output_path = os.path.join(settings.ROOT_PATH, settings.STATIC_URL[1:-1], settings.PROJECT_PATH,
                                       resource_id, "data", "output", "visible")
        else:
            # image_path = SrcData.objects.get(project=project_object).thermal_image
            input_path = os.path.join(settings.ROOT_PATH, settings.STATIC_URL[1:-1], settings.PROJECT_PATH,
                                      resource_id, "data", "src", "thermal")
            output_path = os.path.join(settings.ROOT_PATH, settings.STATIC_URL[1:-1], settings.PROJECT_PATH,
                                       resource_id, "data", "output", "thermal")

        "检测状态"
        analysis_status = apps.get_model("projects", "Project").objects.get(pk=resource_id).analysis_status
        if analysis_status == '0':
            try:
                "创建检测线程"
                check_threading = threading.Thread(target=detect_main,
                                                   args=(input_path, output_path, project_object.id))
                check_threading.start()
            except Exception as e:
                print(e)
            else:
                # 更新检测状态
                project = apps.get_model("projects", "Project").objects.get(project=project_object)
                project.analysis_status = '1'
                project.save()

                return response.Ok({"message": "start check !!!"})
        else:
            return response.Ok({"message": "project data is analyzing"})

    def list(self, request, *args, **kwargs):
        """
        群查（缺陷情况）
        """
        resource_id = kwargs.get("resource_id", None)
        project_model = apps.get_model("projects", "Project")
        project_object = get_object_or_404(project_model.objects.all(), pk=resource_id)

        self.check_permissions(request, 'list', project_object)

        defect_object_list = get_list_or_404(self.get_queryset(), project=project_object)
        if defect_object_list:
            page = self.paginate_queryset(defect_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(defect_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no defect"})


class CheckConfigAdminViewSet(viewsets.ModelViewSet):
    """
    检测配置管理视图
    """
    queryset = models.CheckConfig.objects.all()
    "验证"
    validator_class = validators.CheckConfigValidator
    "序列化"
    serializer_class = serializers.CheckConfigSerializer
    "权限"
    permission_classes = (permissions.CheckConfigAdminPermission,)

    def list(self, request, *args, **kwargs):
        """
        群查（检测配置）
        """
        resource_id = kwargs.get("resource_id", None)
        project_model = apps.get_model("projects", "Project")
        project_object = get_object_or_404(project_model.objects.all(), pk=resource_id)

        self.check_permissions(request, 'list', project_object)

        check_config_object_list = get_list_or_404(self.get_queryset(), project=project_object)
        if check_config_object_list:
            page = self.paginate_queryset(check_config_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(check_config_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no check config"})


class CheckAdminViewSet(viewsets.ModelViewSet):
    """
    检测管理视图
    """
    queryset = models.Defect.objects.all()
    "验证"
    validator_class = validators.DefectValidator
    "序列化"
    serializer_class = serializers.DefectSerializer
    "权限"
    permission_classes = (permissions.CheckAdminPermission,)

    def list(self, request, *args, **kwargs):
        """
        群查（检测配置）
        """
        self.check_permissions(request, 'list', None)

        check_config_object_list = get_list_or_404(self.get_queryset())
        if check_config_object_list:
            page = self.paginate_queryset(check_config_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(check_config_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no check config"})


class CheckTypeAdminViewSet(viewsets.ModelViewSet):
    """
    检测管理视图
    """
    queryset = models.DefectType.objects.all()
    "验证"
    validator_class = validators.DefectTypeValidator
    "序列化"
    serializer_class = serializers.CheckTypeSerializer
    "权限"
    permission_classes = (permissions.CheckAdminPermission,)

    def list(self, request, *args, **kwargs):
        """
        群查（检测配置）
        """
        self.check_permissions(request, 'list', None)

        check_config_object_list = get_list_or_404(self.get_queryset())
        if check_config_object_list:
            page = self.paginate_queryset(check_config_object_list)
            if page is not None:
                serializer = self.get_serializer(page, many=True)
                return self.get_paginated_response(serializer.data)
            else:
                serializer = self.get_serializer(check_config_object_list, many=True)

            return response.Ok(serializer.data)
        else:
            return response.Ok({"message": "Have no check type"})
